//==================================================================
//  Copyright (C) 2006-2007  Davide Pasca
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//==================================================================
///
///
///
///
///
//==================================================================

#ifndef M5D_TVERT_H
#define M5D_TVERT_H

#include <vector>
#include "psys.h"
#include "m5d_mesh_geometry.h"

//==================================================================
class TriList
{
public:
	static const int	FLG_OPEN_EDGE = 1;
	static const int	FLG_DOREMOVE = 2;

private:
	std::vector<int>	_listp;
	int					_pre_cnt;
public:
	int		_flags;

public:
	TriList() :
		_flags(0),
		_pre_cnt(0)
	{
	}

	TriList( const TriList &copy_from ) :
		_listp( copy_from._listp ),
		_flags( copy_from._flags ),
		_pre_cnt(0)
	{
	}

	~TriList()
	{
	}

	void MarkOpenEdges( int vidx, const M5D::MeshGeometry *gp );
	void AddTri( int tidx );
	void RemTri( int tidx );

	void PreallocBegin();
	void PreallocAdd();
	void PreallocEnd();

	//==================================================================
	PFORCEINLINE const int &operator[] (size_t index) const
	{
		return _listp[ index ];
		//return _listp.at( index );
	}
	//==================================================================
	PFORCEINLINE int &operator[] (size_t index)
	{
		return _listp[ index ];
		//return _listp.at( index );
	}

	//==================================================================
	PFORCEINLINE const size_t len() const
	{
		return _listp.size();
	}

private:
	bool FindTriangleWithVerts( int exclude_tri, const M5D::MeshGeometry *gp, int v1, int v2 );
};

//==================================================================
class TriIdx_VertIdx
{
	std::vector<TriList>	_lists;

public:
	TriIdx_VertIdx( const M5D::MeshGeometry *gp );

	inline void MarkVertForRemoval( int vidx )
	{
		PASSERT( vidx >= 0 && vidx < _lists.size() );
		_lists[ vidx ]._flags |= TriList::FLG_DOREMOVE;
	}

	inline bool IsVertMarkedForRemoval( int vidx )
	{
		PASSERT( vidx >= 0 && vidx < _lists.size() );
		return (_lists[ vidx ]._flags & TriList::FLG_DOREMOVE) != 0;
	}


	int ReplaceVertex( int good_vidx, int kill_vidx, M5D::MeshGeometry *gp );

	void RemoveMarkedVerts();

	//==================================================================
	const TriList &operator[] (size_t index) const
	{
		return _lists[ index ];
		//return _lists.at( index );
	}
	//==================================================================
	TriList &operator[] (size_t index)
	{
		return _lists[ index ];
		//return _lists.at( index );
	}

	//==================================================================
	const size_t len() const
	{
		return _lists.size();
	}

private:
	void preallocTrilists( const M5D::MeshGeometry *gp );
	void createTrilists( const M5D::MeshGeometry *gp );
};

//==================================================================
PError tvert_update_vert_count( TriIdx_VertIdx *T, M5D::MeshGeometry *gp );

#endif